"use client"

import { Member, Message, Profile } from "@prisma/client";
import { ChatWelcome } from "./chat-welcome";
import { useChatQuery } from "@/hooks/use-chat-query";
import { Loader2 } from "lucide-react";
import { ElementRef, Fragment, useRef } from "react";
import { ChatItem } from "./chat-item";
import {format} from "date-fns"
import { useChatSocket } from "@/hooks/use-chat-socket";
import { useChatScroll } from "@/hooks/use-chat-scroll";

const DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"

type MessageWithMemberWithProfile = Message & {
    member: Member & {
        profile: Profile
    }
}

interface ChatMessagesProps {
    name: string;
    member: Member;
    chatId: string;
    apiUrl:string;
    socketUrl:string;
    socketQuery: Record<string, string>;
    paramKey: "channelId" | "conversationId"
    paramValue: string;
    type: "channel" | "conversation"
}

export const ChatMessages = ({
    name,
    member,
    chatId,
    apiUrl,
    socketUrl,
    socketQuery,
    paramKey,
    paramValue,
    type,
}: ChatMessagesProps) => {
    
    const queryKey = `chat:${chatId}`;
    const addKey = `chat:${chatId}:messages`
    const updateKey = `chat:${chatId}:messages:update`

    const chatRef = useRef<ElementRef<"div">>(null);
    const bottomRef = useRef<ElementRef<"div">>(null);


    const {
        data,
        fetchNextPage,
        hasNextPage,
        isFetchingNextPage,
        status
    } = useChatQuery({
        queryKey,
        apiUrl,
        paramKey,
        paramValue
    })

    useChatSocket({queryKey, addKey, updateKey})
    useChatScroll({
        chatRef,
        bottomRef,
        loadMore: fetchNextPage,
        shouldLoadMore: !isFetchingNextPage && !!hasNextPage,
        count: data?.pages?.[0]?.items?.length ?? 0
    })

    if(status === "pending") {
        return (
            <div className="flex flex-col flex-1 justify-center items-center">
                <Loader2 className="h-7 w-7 text-zinc-500 animate-spin my-4"></Loader2>
                <p className="text-xs text-zinc-500 dark:text-zinc-400">
                    Loading messages..
                </p>
            </div>
        )
    }

    if(status === "error") {
        return (
            <div className="flex flex-col flex-1 justify-center items-center">
                <Loader2 className="h-7 w-7 text-zinc-500 animate-spin my-4"></Loader2>
                <p className="text-xs text-zinc-500 dark:text-zinc-400">
                    Something went wrong!
                </p>
            </div>
        )
    }

    return (
        <div ref={chatRef} className="flex-1 flex flex-col py-4 overflow-y-auto">
            {!hasNextPage && <div className="flex-1" />}
            {!hasNextPage && (
                <ChatWelcome type={type} name={name}></ChatWelcome>
            )}
            {hasNextPage && (
                <div className="flex justify-center">
                    {
                        isFetchingNextPage ? (
                            <Loader2 className="h-6 w-6 text-zinc-500 animate-spin my-4"></Loader2>
                        ) : (
                            <button 
                                onClick={() => fetchNextPage()}
                                className="text-zinc-500 hover:text-zinc-600 dark:text-zinc-400 text-xs ,u-4 dark:hover:text-zinc-300 transition">
                                Load previous messages
                            </button>
                        )
                    }
                </div>
            )}
            <div className="flex flex-col-reverse mt-auto">
                {data?.pages.map((group,i)=>(
                    <Fragment key={i}>
                        {group.items.map((m: MessageWithMemberWithProfile) => (
                            <ChatItem 
                                key={m.id}
                                id={m.id}
                                currentMember={member}
                                member={m.member}
                                content={m.content}
                                fileUrl={m.fileUrl}
                                deleted={m.deleted}
                                timestamp={format(new Date(m.createAt), DATE_FORMAT)}
                                isUpdated={m.updateAt !== m.createAt}
                                socketUrl={socketUrl}
                                socketQuery={socketQuery}
                                />
                        ))}
                    </Fragment>
                ))}
            </div>
            <div ref={bottomRef}></div>
        </div>
    )
}